package me.shiqiang.im.utils;


import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by xingzu on 2018/8/16.
 */

public class AliyunUtils {
    private static final String ENCODING = "UTF-8";
    private static final String Format = "JSON";
    private static final String VERSION = "2016-11-01";
    private static final String SignatureMethod = "HMAC-SHA1";
    private static final String SignatureVersion = "1.0";
    private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
    private static final String ALGORITHM = "HmacSHA1";
    private static final String HTTP_METHOD = "GET";



    /**
     * @return
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     * @throws NoSuchAlgorithmException
     */
    public static String getSignedQueryString(Map<String, String> parameters) throws UnsupportedEncodingException,
            InvalidKeyException, NoSuchAlgorithmException {


        // 加入请求参数
        parameters.put("Version", VERSION);
//        parameters.put("AccessKeyId", "LTAIXbwPIG4caDuT");//输入你的 Access Key ID
        parameters.put("Timestamp", formatIso8601Date(new Date()));
        parameters.put("SignatureMethod", SignatureMethod);
        parameters.put("SignatureVersion", SignatureVersion);
        parameters.put("SignatureNonce", UUID.randomUUID().toString());
        parameters.put("Format", Format);

        // 对参数进行排序，注意严格区分大小写
        String[] sortedKeys = parameters.keySet().toArray(new String[]{});
        Arrays.sort(sortedKeys);

        final String SEPARATOR = "&";

        // 生成stringToSign字符串
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(HTTP_METHOD).append(SEPARATOR);
        stringToSign.append(percentEncode("/")).append(SEPARATOR);

        StringBuilder canonicalizedQueryString = new StringBuilder();
        for (String key : sortedKeys) {
            // 这里注意对key和value进行编码
            canonicalizedQueryString.append("&")
                    .append(percentEncode(key)).append("=")
                    .append(percentEncode(parameters.get(key)));
        }

        // 这里注意对canonicalizedQueryString进行编码
        stringToSign.append(percentEncode(canonicalizedQueryString.toString().substring(1)));

        String signature = getSignature(stringToSign.toString());

        canonicalizedQueryString.append("&")
                .append("Signature").append("=")
                .append(percentEncode(signature));

        return canonicalizedQueryString.toString();
    }

    private static String formatIso8601Date(Date date) {
        SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }


    private static String percentEncode(String value) throws UnsupportedEncodingException {
        return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;
    }

    private static String getSignature(String stringToSign) throws InvalidKeyException, UnsupportedEncodingException, NoSuchAlgorithmException {
        String key = "OUF2CS0F2iqLF6MqiWwa5Nw7iLkHEW" + "&";//注意 key = Access Key Secret +"&"

        Mac mac = Mac.getInstance(ALGORITHM);
        mac.init(new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM));
        byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));

        String signature = new String(Base64.encodeBase64(signData));
        return signature;

    }

}